package com.wan.data.resource.parser.impl;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import com.wan.data.resource.converter.ConverterManager;
import com.wan.data.resource.model.IModel;
import com.wan.data.resource.parser.ResourceParser;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * excel解析器
 * @author wwh
 * @date 2022/7/4 20:30
 */
public class ExcelParser implements ResourceParser {
    private static final int HEAD = 3;

    @Override
    public String[] suffixes() {
        return new String[]{"xls","xlsx"};
    }

    @Override
    public <R extends IModel<?>> List<R> parse(File file, Class<R> resourceModelCls) throws Exception {
        List<List<Object>> read = read(file);
        if(read.size() < HEAD){
            throw new RuntimeException("excel表头格式不正确->" + file.getName());
        }
        //首行->列名
        List<Object> names = read.remove(0);
        //第二行->类型,暂时用不上
        read.remove(0);
        //第三行->描述
        read.remove(0);
        return reflectToBean(names,read,resourceModelCls);
    }

    /**
     * 从excel读取出原始数据
     * @param file excel
     */
    protected List<List<Object>> read(File file) {
        List<List<Object>> objects = new ArrayList<>();
        ExcelUtil.readBySax(file, 0, (sheetIndex, rowIndex, rowCells) -> {
            objects.add(rowCells);
        });
        return objects;
    }

    /**
     * 把原始数据转换成model列表
     * 根据现有Model类型解析，当前规则：
     * 【Model没有，excel有】 ->不解析
     * 【Model有，excel没有】 ->不解析
     * 名称转义,model:驼峰,excel:下划线分隔
     * 如果有更严格的要求可以在上述规则下抛错
     * @param names 表头名
     * @param data 数据
     */
    private <R extends IModel<?>>List<R> reflectToBean(List<Object> names,List<List<Object>> data,Class<R> modelClass) throws IllegalAccessException {
        List<R> modelList = new ArrayList<>();
        //表头首列去除，对应状态位
        names.remove(0);
        for (List<Object> row : data) {
            if(row.size() <= 0){
                continue;
            }
            //首列置为状态位，不大于零则代表该行不读取
            int status = Integer.parseInt(row.remove(0).toString());
            if(status <= 0){
                continue;
            }
            R model = ReflectUtil.newInstance(modelClass);
            for (int i = 0; i < row.size(); i++) {
                String name = names.get(i).toString();
                Field field;
                try {
                    //下划线命名转驼峰
                    field = modelClass.getDeclaredField(StrUtil.toCamelCase(name));
                } catch (NoSuchFieldException ignored) {
                    continue;
                }
                field.setAccessible(true);
                //通过转换器转换原始数据
                Object convert = ConverterManager.convert(field.getType(), row.get(i));
                field.set(model, convert);
            }
            //属性注入完毕，执行后置处理
            model.afterInit();
            modelList.add(model);
        }
        return modelList;
    }

}
